/*
* 扩展功能测试
*/

#include "../LogSystemCode/mylog.h"
#include <unistd.h>


//测试sink.hpp 可扩展的支持
//按天数滚动文件
enum class TimeGap //滚动大小
{
    GAP_SECOND, //以秒为步数
    GAP_MINUTE, //分
    GAP_HOUR,   //时
    GAP_DAY     //天
};

//日志向滚动文件输出落地
class RollByTimeSink : public Log::LogSink
{
public:
    //将文件路径记录起来 建立句柄(IO)管理
    RollByTimeSink(const std::string& basename,TimeGap TimeType):_basename(basename)
    {
        switch(TimeType)
        {
            case TimeGap::GAP_SECOND: _gap_time = 1;break;
            case TimeGap::GAP_MINUTE: _gap_time = 60;break;
            case TimeGap::GAP_HOUR: _gap_time = 60*60;break;
            case TimeGap::GAP_DAY: _gap_time = 60*60*24;break;
        }

        //1.创建文件所在目录 - 获取文件路径 创建对应目录
        std::string pathname = createNewFile();
        Log::LogUtil::File::createDirectory(Log::LogUtil::File::path(pathname));
        //2.创建和打开文件
        _ofs.open(pathname,std::ios::binary | std::ios::app); //以二进制打开 并追加写入
        assert(_ofs.is_open()); //验证是否成功打开文件

        _cur_time = Log::LogUtil::Date::now() % _gap_time;
    }

    void log(const char *data, size_t len) override
    {
        //文件写入满了 先关闭当前文件 再创建新文件
        time_t now_time = Log::LogUtil::Date::now() % _gap_time;
        if( now_time == _cur_time )
        {
            _ofs.close();
            //创建新文件名
            std::string pathname = createNewFile();
            //创建新文件
            _ofs.open(pathname,std::ios::binary | std::ios::app);
            assert(_ofs.is_open());
            _cur_time = Log::LogUtil::Date::now() % _gap_time;
        }
        _ofs.write(data,len);
        assert(_ofs.good()); //写入后检查句柄是否还正常 如果不正常则写入失效
    }

private:
    //进行文件大小判断 如果文件写到规定大小则立刻按时间生成文件名生成新文件
    std::string createNewFile()
    {
        time_t t = Log::LogUtil::Date::now();
        struct tm nowt;
        localtime_r(&t,&nowt);
        std::stringstream ss;
        ss << _basename;
        ss << nowt.tm_yday + 1900; //年 系统从1900开始计时
        ss << nowt.tm_mon + 1; //月
        ss << nowt.tm_mday; //日
        ss << nowt.tm_hour; //时
        ss << nowt.tm_min; //分
        ss << nowt.tm_sec; //秒
        ss << ".log"; //后缀
        return ss.str();
    }
private:
    //通过 基础文件名+扩展文件名(以时间为扩展文件名)组成一个实际的当前输出的文件名
    std::string _basename; //文件路径 例如:./log/base-20030314202020.log(或定义一个计数器 生成 base-1.log ...)
    std::ofstream _ofs; //标准文件流
    time_t _gap_time; //文件的间隔时间模
    time_t _cur_time; //文件的当前创建时间
};

//落地扩展功能测试
void test_log(const std::string& name)
{
    DEFINFO("测试开始");
    Log::Logger::ptr logger = Log::LoggerManager::getInstance().getLogger(name);

    int n = 125;
    while(n--)
    {
        logger->DEBUGLOG("测试日志-%d",0);
        logger->INFOLOG("测试日志-%d",0);
        logger->WARNLOG("测试日志-%d",0);
        logger->ERRORLOG("测试日志-%d",0);
        logger->FATALLOG("测试日志-%d",0);
        sleep(1);
        std::cout<<n<<std::endl;
    }


    DEFINFO("测试结束");
}

int main()
{
    std::unique_ptr<Log::LoggerBuilder> logbuild(new Log::GlobalLoggerBuilder);
    logbuild->buildLoggerType(Log::LoggerType::LOGGER_ASYNC); //设置为异步日志器
    logbuild->buildFormatter("[%d{%Y-%m-%d|%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n");
    logbuild->buildLoggerLevel(Log::LogLevel::value::WARN);
    logbuild->buildLoggerName("测试器");

    logbuild->buildSink<RollByTimeSink>("./log/base-",TimeGap::GAP_MINUTE); //滚动文件输出 以分为单位

    //添加到全局日志器中管理
    logbuild->build();

    test_log("测试器");

    return 0;
}